using AutoMapper;
using Core.SimpleTemp.Common;
using Core.SimpleTemp.Common.PagingQuery;
using Core.SimpleTemp.Entitys;
using Core.SimpleTemp.Repositories;
using Core.SimpleTemp.Repositories.Sys;
using Core.Toolkit.Common;
using Core.Toolkit.Core;
using Core.Toolkit.Core.Api;
using Core.Toolkit.Core.Application;
using Microsoft.EntityFrameworkCore;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace Core.SimpleTemp.Application
{
    [AutoDi()]
    public class PX_ExamService : BaseAppService<PX_ExamDto, PX_Exam, PX_ExamRepository>
    {
        readonly ExcelHelp _excelHelp;
        PX_ExamRecordRepository _recordrespository;
        public PX_ExamService(PX_ExamRepository repository, PX_ExamRecordRepository recordrespository, ExcelHelp excelHelp) : base(repository)
        {
            _excelHelp = excelHelp;
            _recordrespository = recordrespository;
        }



        private LoadPageOffsetModelAuto<PX_Exam, PX_ExamDto>
            GetLoadPageOffsetMode(PagingModel<PX_ExamDto> pagingQueryModel)
        {
            var loadPageOffsetModel = this.GetLoadPageOffsetModelAuto(pagingQueryModel);
            var baseQuery = _repository.QueryBase().AsNoTracking().Include(a => a.PX_ExamUser).Include(a => a.PX_Plan);
            loadPageOffsetModel.QueryWhere = this.CreateQRList().Add("PX_Plan.Nameoftrainingplan", "in");//培训名称

            //.Add("PlanId", "=")
            //.Add("facilityvalue", "=")
            //.Add("Fullmarks", "=")
            //.Add("Qualificationscore", "=")
            //.Add("JudgmentNumber", "=")
            //.Add("JudgmentScore", "=")
            //.Add("SingleNumber", "=")
            //.Add("SingleScore", "=")
            //.Add("MultipleNumber", "=")
            //.Add("MultipleScore", "=")
            //.Add("Examinationstarttime", "=")
            //.Add("Endtimeofexamination", "=")
            //.Add("Examinationmethods", "=")
            //.Add("Place", "=")
            //.Add("IsShow", "=")
            //.Add("IsNotice", "=")
            //.Add("Status", "=")
            //.Add("CreateFactory", "=")
            //.Add("CreateDept", "=")
            //.Add("UpdateDept", "=");


            loadPageOffsetModel.BasqQuery = baseQuery;
            loadPageOffsetModel.Order = orderModel => orderModel.CreateTime;
            //loadPageOffsetModel.Selector = model => new PX_Exam()
            //{
            //    Id = model.Id,
            //    PlanId = model.PlanId,
            //    facilityvalue = model.facilityvalue,
            //    Fullmarks = model.Fullmarks,
            //    Qualificationscore = model.Qualificationscore,
            //    JudgmentNumber = model.JudgmentNumber,
            //    JudgmentScore = model.JudgmentScore,
            //    SingleNumber = model.SingleNumber,
            //    SingleScore = model.SingleScore,
            //    MultipleNumber = model.MultipleNumber,
            //    MultipleScore = model.MultipleScore,
            //    Examinationstarttime = model.Examinationstarttime,
            //    Endtimeofexamination = model.Endtimeofexamination,
            //    Examinationmethods = model.Examinationmethods,
            //    Place = model.Place,
            //    IsShow = model.IsShow,
            //    IsNotice = model.IsNotice,
            //    Status = model.Status,
            //    CreateFactory = model.CreateFactory,
            //    CreateDept = model.CreateDept,
            //    UpdateDept = model.UpdateDept,
            //};
            return loadPageOffsetModel;
        }


        public async Task<IPageModel<PX_ExamDto>> GetList(PagingModel<PX_ExamDto> pagingQueryModel)
        {
            var loadPageOffsetModel = GetLoadPageOffsetMode(pagingQueryModel);
            return await base.LoadPageOffsetAsync(loadPageOffsetModel);
        }




        public async Task<List<PX_ExamUserQuestionsDto>> cjks(Guid id, String type)
        {
            //传过来的id是 planuser的  转换成 examuser 的id
            if (type != "3") {
                PX_PlanUser pu = _repository._dbContext.PX_PlanUser.Where(x => x.Id == id).FirstOrDefault();
                PX_ExamUser eu = _repository._dbContext.PX_ExamUser.Where(x => x.PX_PlanId == pu.PlanID && x.PersonID == pu.PersonID).FirstOrDefault();
                id = eu.Id;
                
            }
            

            return await DealExam(id, type);

        }

        //考试统一处理方法 在线/模拟 考试人员表 PX_ExamPerson ID
        public async Task<List<PX_ExamUserQuestionsDto>> DealExam(Guid id, string type)
        {
            PX_ExamUser pep = await _repository._dbContext.PX_ExamUser.Where(x => x.Id == id).FirstOrDefaultAsync();
            //模拟0 正考1  错题3
            //判断是否需要继续答题 逻辑：如果是有未完成的在线考试， 允许开始模拟考试   继续在线考试  反之也是。
            //若type为1 则判断考试次数是否大于等于5  大于5则不允许答题

            if (type == "1")
            {
                
                
            }
            List<PX_ExamUserQuestionsDto> tm;
            if (type == "3") {
                //已通过  只答错题  此时id 是 ExamRecord的id 找到其下所有错题 返回
                var list = _recordrespository._dbContext.PX_ExamUserQuestions.Where(x => x.PersonID == id && x.CorrectOption != x.LastOption)
                    .OrderBy(x => x.CreateTime).ToList();
                tm = Mapper.Map<List<PX_ExamUserQuestionsDto>>(list);
                foreach (PX_ExamUserQuestionsDto dto in tm)
                {
                    dto.PX_QuestionOption = await _repository._dbContext.PX_QuestionsOptions.Where(x => x.QuestionsId == dto.QuesiontID).OrderBy(x => x.OptionName).ToListAsync();
                }
            }
            else
            { //生成试卷 并返回试题
                //找到所有当前考试类别下 对应的 未提交或 已提交 未通过的
                List<PX_ExamRecord> list = await _repository._dbContext.PX_ExamRecord.Where(x => x.PersonID == id && x.Type == type && (x.IsCommit == "0" || pep.Qualificationscore<=x.Score) &&x.Mark04!="已满分").Include(x=>x.PX_ExamUserQuestions ).ToListAsync();
                List<PX_ExamRecord> listcount = await _repository._dbContext.PX_ExamRecord.Where(x => x.PersonID == id && x.Type == type ).Include(x => x.PX_ExamUserQuestions).ToListAsync();
                if (!list.Any())
                    tm = await CreateExam(id, type, list,listcount);
                else
                {
                    tm = await ContinueExam(id, type, list, pep.Qualificationscore <= list.FirstOrDefault().Score);
                }
            }
            return tm;
        }

        //考试试卷生成 在线/模拟 考试人员表 PX_ExamPerson ID 接着答题
        public async Task<List<PX_ExamUserQuestionsDto>> ContinueExam(Guid id, string type, List<PX_ExamRecord> list,bool IsTG)
        {
            var questionlist = await _repository._dbContext.PX_ExamUserQuestions.Where(x => x.PersonID == list.FirstOrDefault().Id).ToListAsync();
            PX_ExamRecordDto epr = new PX_ExamRecordDto();
            //如果通过 并且不是模拟  过滤正确选项的题目
            if (IsTG && type != "0") {
                questionlist=questionlist.Where(x => x.LastOption != x.CorrectOption).ToList();
                questionlist.ForEach(x => { x.Mark01 = "答错题"; });
            }
            epr.PX_ExamUserQuestions = Mapper.Map<List<PX_ExamUserQuestionsDto>>(questionlist);
            foreach (PX_ExamUserQuestionsDto a in epr.PX_ExamUserQuestions)
            {
                List<PX_QuestionsOptions> optionlist = _repository._dbContext.PX_QuestionsOptions.Where(x => x.QuestionsId == a.QuesiontID).OrderBy(x => x.OptionName).ToList();
                a.PX_QuestionOption = optionlist;
                a.CorrectOption = "";
            }
            
            return epr.PX_ExamUserQuestions.OrderBy(x=>x.CreateTime).ToList();
        }


        //考试试卷生成 在线/模拟 考试人员表 PX_ExamPerson ID  首次答题
        public async Task<List<PX_ExamUserQuestionsDto>> CreateExam(Guid id, string type, List<PX_ExamRecord> list, List<PX_ExamRecord> listcount)
        {
            

            //生成考试人员记录 PX_ExamPersonRecord
            PX_ExamRecordDto epr = new PX_ExamRecordDto();
            epr.PX_ExamUserQuestions = new List<PX_ExamUserQuestionsDto>();
            epr.Id = Guid.NewGuid();
            epr.Examinationstarttime = DateTime.Now;
            epr.IsCommit = "0";
            epr.PersonID = id;
            epr.Times = listcount.Count + 1;
            epr.Type = type;
            

            

            

            //根据考试PX_Exam设置 关联 计划表与试题表  生成考试记录试题  PX_ExamRecordQuestion
            var examperson = await _repository._dbContext.PX_ExamUser.Where(y => y.Id == id).FirstOrDefaultAsync();
            PX_Exam exam = await _repository._dbContext.PX_Exam.Where(x => x.Id == examperson.ExamId).FirstOrDefaultAsync();
            PX_Plan plan = await _repository._dbContext.PX_Plan.Where(x => x.Id == examperson.PX_PlanId).FirstOrDefaultAsync();

            List<PX_Questions> questionlist = await _repository._dbContext.PX_Questions.Where(x => x.trainingcourse == plan.trainingcourse).ToListAsync();
            if (questionlist.Any())
            {//2判断 0单选 1多选
                //exam.Level 简单 0 中等1 困难2 先取Level一致的 如果题目不够 再从其他Level中随机取题目
                List<PX_Questions> pdquestionlist = questionlist.Where(x => x.QuestionManagementType == "2" && x.DegreeOfDifficulty == exam.facilityvalue).ToList();
                List<PX_Questions> danxquestionlist = questionlist.Where(x => x.QuestionManagementType == "0" && x.DegreeOfDifficulty == exam.facilityvalue).ToList();
                List<PX_Questions> duoxquestionlist = questionlist.Where(x => x.QuestionManagementType == "1" && x.DegreeOfDifficulty == exam.facilityvalue).ToList();
                //随机题目
                //分别随机 判断 单选 多选 拼接 题目数量在 exam中  题目来源在 questionlist中
                List<PX_ExamUserQuestionsDto> pdresult = new List<PX_ExamUserQuestionsDto>();
                List<PX_ExamUserQuestionsDto> danxresult = new List<PX_ExamUserQuestionsDto>();
                List<PX_ExamUserQuestionsDto> duoxresult = new List<PX_ExamUserQuestionsDto>();
                if (pdquestionlist.Count <= exam.JudgmentNumber.Value)
                {
                    pdquestionlist.ForEach(q =>
                    {

                        List<PX_QuestionsOptions> optionlist = _repository._dbContext.PX_QuestionsOptions.Where(x => x.QuestionsId == q.Id).OrderBy(x => x.OptionName).ToList();
                        PX_ExamUserQuestionsDto erq = new PX_ExamUserQuestionsDto();
                        erq.PX_QuestionOption = optionlist;
                        questionlist.Remove(q);

                        
                        erq.Mark01 = q.QuestionManagementType;
                        erq.PersonID = epr.Id;
                        erq.Id = Guid.NewGuid();
                        erq.QuesiontID = q.Id;
                        erq.QuestionContent = q.QuestionManagementContent;
                        erq.CorrectOption = "";
                        optionlist.Where(a => a.IsAnswer == "是").OrderBy(x => x.OptionName).ToList().ForEach(x => erq.CorrectOption += x.OptionName + ",");
                        erq.CorrectOption = erq.CorrectOption.TrimEnd(',');
                        erq.dxda = new List<String>();

                        pdresult.Add(erq);
                    });
                    randomQuestion(epr.Id, exam.JudgmentNumber.Value - pdquestionlist.Count, questionlist.
                        Where(x => x.QuestionManagementType == "2" && x.DegreeOfDifficulty != exam.facilityvalue).ToList(), new List<PX_ExamUserQuestionsDto>())
                        .ForEach(y => pdresult.Add(y)); ;
                }
                else
                {
                    pdresult = randomQuestion(epr.Id, exam.JudgmentNumber.Value, pdquestionlist, new List<PX_ExamUserQuestionsDto>());
                }
                if (danxquestionlist.Count <= exam.SingleNumber.Value)
                {
                    danxquestionlist.ForEach(q =>
                    {
                        List<PX_QuestionsOptions> optionlist = _repository._dbContext.PX_QuestionsOptions.Where(x => x.QuestionsId == q.Id).OrderBy(x => x.OptionName).ToList();
                        PX_ExamUserQuestionsDto erq = new PX_ExamUserQuestionsDto();
                        erq.PX_QuestionOption = optionlist;
                        questionlist.Remove(q);

                        erq.Mark01 = q.QuestionManagementType;
                        erq.PersonID = epr.Id;
                        erq.Id = Guid.NewGuid();
                        erq.QuesiontID = q.Id;
                        erq.QuestionContent = q.QuestionManagementContent;
                        erq.CorrectOption = "";
                        optionlist.Where(a => a.IsAnswer == "是").OrderBy(x => x.OptionName).ToList().ForEach(x => erq.CorrectOption += x.OptionName + ",");
                        erq.CorrectOption = erq.CorrectOption.TrimEnd(',');
                        erq.dxda = new List<String>();

                        pdresult.Add(erq);
                    });
                    randomQuestion(epr.Id, exam.SingleNumber.Value - danxquestionlist.Count, questionlist.
                        Where(x => x.QuestionManagementType == "0" && x.DegreeOfDifficulty != exam.facilityvalue).ToList(), new List<PX_ExamUserQuestionsDto>())
                        .ForEach(y => danxresult.Add(y));
                }
                else
                {
                    danxresult = randomQuestion(epr.Id, exam.SingleNumber.Value, danxquestionlist, new List<PX_ExamUserQuestionsDto>());
                }
                if (duoxquestionlist.Count <= exam.MultipleNumber.Value)
                {
                    duoxquestionlist.ForEach(q =>
                    {
                        List<PX_QuestionsOptions> optionlist = _repository._dbContext.PX_QuestionsOptions.Where(x => x.QuestionsId == q.Id).OrderBy(x => x.OptionName).ToList();
                        PX_ExamUserQuestionsDto erq = new PX_ExamUserQuestionsDto();
                        erq.PX_QuestionOption = optionlist;
                        questionlist.Remove(q);

                        erq.Mark01 = q.QuestionManagementType;
                        erq.PersonID = epr.Id;
                        erq.Id = Guid.NewGuid();
                        erq.QuesiontID = q.Id;
                        erq.QuestionContent = q.QuestionManagementContent;
                        erq.CorrectOption = "";
                        optionlist.Where(a => a.IsAnswer == "是").OrderBy(x => x.OptionName).ToList().ForEach(x => erq.CorrectOption += x.OptionName + ",");
                        erq.CorrectOption = erq.CorrectOption.TrimEnd(',');
                        erq.dxda = new List<String>();

                        pdresult.Add(erq);
                    });
                    randomQuestion(epr.Id, exam.MultipleNumber.Value - duoxquestionlist.Count, questionlist
                        .Where(x => x.QuestionManagementType == "1" && x.DegreeOfDifficulty != exam.facilityvalue).ToList(), new List<PX_ExamUserQuestionsDto>())
                         .ForEach(y => duoxresult.Add(y));
                }
                else
                {
                    duoxresult = randomQuestion(epr.Id, exam.MultipleNumber.Value, duoxquestionlist, new List<PX_ExamUserQuestionsDto>());
                }

                pdresult.ForEach(x => {
                   
                    epr.PX_ExamUserQuestions.Add(x);
                });
                danxresult.ForEach(x => {
                   
                    epr.PX_ExamUserQuestions.Add(x);
                });
                duoxresult.ForEach(x => {
                    
                    epr.PX_ExamUserQuestions.Add(x);
                });
            }



            var result=await _recordrespository.InsertAsync(Mapper.Map<PX_ExamRecord>(epr));
            
            return epr.PX_ExamUserQuestions.OrderBy(x=>x.CreateTime).ToList();
        }

        public async Task lastornext(PX_ExamUserQuestionsDto dto)
        {
            PX_ExamUserQuestions erq = await _recordrespository._dbContext.PX_ExamUserQuestions.Where(x => x.Id == dto.Id).FirstOrDefaultAsync();
            
            erq.LastOption = dto.LastOption;
            await _recordrespository.SaveAsync();
        }

        //提交试卷 暂存/提交  提交一道题目 与变更试卷状态 
        public async Task<Guid> tjsj(PX_ExamUserQuestionsDto dto)
        {
            //如果是提交  将PX_ExamPersonRecord 状态变为 已提交  endtime =Now 并计算得分  返回得分结果与是否通过
            if (dto.Mark03 == "999") {
                PX_PlanUser mpu = new PX_PlanUser();
                PX_ExamUser meu = new PX_ExamUser();
                if (dto.Mark02 != "3")
                {
                    mpu = _repository._dbContext.PX_PlanUser.Where(x => x.Id == dto.Id).FirstOrDefault();
                    meu = _repository._dbContext.PX_ExamUser.Where(x => x.PX_PlanId == mpu.PlanID && x.PersonID == mpu.PersonID).FirstOrDefault();
                }
                else {
                    meu = _repository._dbContext.PX_ExamUser.Where(x => x.Id == dto.Id).FirstOrDefault();
                    mpu = _repository._dbContext.PX_PlanUser.Where(x => x.PlanID == meu.PX_PlanId && x.PersonID == meu.PersonID).FirstOrDefault();
                }

                PX_ExamRecord er= _repository._dbContext.PX_ExamRecord.Where(x => x.PersonID == meu.Id&&x.Score>=meu.Qualificationscore && x.IsCommit=="1" &&x.Type== dto.Mark02 && x.Mark04 != "已满分").FirstOrDefault();


                meu.IsQualified = "1";
                mpu.IsQualified = "1";
                er.Mark04 = "已满分";
                await _repository.SaveAsync();
                return er.Id;


            }
            PX_ExamUserQuestions erq = await _recordrespository._dbContext.PX_ExamUserQuestions.Where(x => x.Id == dto.Id).FirstOrDefaultAsync();
            erq.LastOption = dto.LastOption;
            
            await _recordrespository.SaveAsync();
           
            PX_ExamRecord epr = await _recordrespository._dbContext.PX_ExamRecord.Where(x => x.Id == erq.PersonID).FirstOrDefaultAsync();
           
            PX_ExamUser ep = await _recordrespository._dbContext.PX_ExamUser.Where(x => x.Id == epr.PersonID).FirstOrDefaultAsync();
            List<PX_ExamUserQuestions> epqlist = await _recordrespository._dbContext.PX_ExamUserQuestions.
                Where(x => x.PersonID == epr.Id &&
                (epr.IsCommit == "1"?x.CorrectOption!=x.LastOption:true)).ToListAsync();
            if (epr.IsCommit != "1")
                epr.IsCommit = "1";
            epr.Endtimeofexamination = DateTime.Now;
            PX_Exam e = await _recordrespository._dbContext.PX_Exam.Where(x => x.Id == ep.ExamId).FirstOrDefaultAsync();
            PX_PlanUser pu = _recordrespository._dbContext.PX_PlanUser.Where(x => x.PersonID == ep.PersonID && x.PlanID == ep.PX_PlanId).FirstOrDefault();
            //计算得分 获取PX_Exam 中 题目分类对应得分   获取 PX_Question 题目分类 
            double eprScore = 0;
            int errornum = 0;
            int currnum = 0;
            var pds = e.JudgmentScore;
            var danxs = e.SingleScore;
            var duoxs = e.MultipleScore;
            foreach (PX_ExamUserQuestions er in epqlist)
            {
                if (er.FirstOption == null)
                    er.FirstOption = er.LastOption;
                if (er.LastOption == er.CorrectOption)
                {
                    currnum++;
                    PX_Questions pxq = await _recordrespository._dbContext.PX_Questions.Where(x => x.Id == er.QuesiontID).FirstOrDefaultAsync();
                    if (pxq.QuestionManagementType == "0")
                    {
                        eprScore += danxs.Value;
                    }
                    if (pxq.QuestionManagementType == "1")
                    {
                        eprScore += duoxs.Value;
                    }
                    if (pxq.QuestionManagementType == "2")
                    {
                        eprScore += pds.Value;
                    }
                }
                else
                {
                    errornum++;
                }
            }

            
            //如果是 在线考试则 或通过后补答 考试次数++；如果通过了 参与状态变为通过;分数如果高过以往分数则替换
            //非答 错题的线上考试
            if ( string.IsNullOrEmpty(epr.Mark04))
            {
                epr.Score = eprScore;
                ep.Numberofexaminations = epr.Times;
                //ep.Examinationscore = ep.Examinationscore < eprScore ? eprScore : ep.Examinationscore;
                ep.Examinationscore = eprScore;
                pu.Score = Decimal.Parse(ep.Examinationscore.ToString());

                //通过的
                if (eprScore >= ep.Qualificationscore)
                {
                    //直接满分的
                    if (eprScore == ep.Fullmarks)
                    {
                        //PX_PlanUser  pu Score IsQualified
                        //PX_ExamUser  ep IsQualified Examinationscore Numberofexaminations
                        //PX_ExamRecord epr Score IsCommit Times
                        ep.IsQualified ="1" ;
                        pu.IsQualified = ep.IsQualified;
                        epr.Mark04 = "已满分";
                    }
                    //通过但未满分的
                    else {
                        epr.Mark04 = "已通过";
                    }
                }
                //直接未通过的
                else {
                    epr.Mark04 = "未通过";
                }
            }
            if (epr.Type == "0") {
                epr.Score = eprScore;
                epr.Mark04 = "模拟考试";
            }
            if (epr.Mark04 == "已通过") {
                //已通过 复 答 错题
                
                if (epqlist.Count() > 0)
                {
                    //仍有错题
                    epr.Mark04 = "已通过";
                }
                else {
                    //已答对
                    ep.IsQualified = "1";
                    pu.IsQualified = ep.IsQualified;
                    epr.Mark04 = "已满分";
                }

            }

           
            //epr.Mark04 = epr.Score.ToString();
            epr.Mark02 = errornum.ToString();
            epr.Mark03 = currnum.ToString();
            await _recordrespository.SaveAsync();

            //Dictionary<bool, Decimal> di = new Dictionary<bool, decimal>();
            //di.Add(epr.Score >= ep.QualifiedScore, epr.Score);



            return epr.Id;
        }



        //随机题目
        public List<PX_ExamUserQuestionsDto> randomQuestion(Guid Id, int examnum, List<PX_Questions> questionlist, List<PX_ExamUserQuestionsDto> list)
        {
            //在题目中随机一道题目 add到 list ;examnum--; questionlist remove掉对应数据  递归调用 直到examnum==0

            if (examnum == 0)
            {
                return list;
            }
            else
            {
                Random r = new Random();
                int num = r.Next(questionlist.Count);
                examnum--;


                PX_Questions q = questionlist.GetRange(num, 1).FirstOrDefault();
                List<PX_QuestionsOptions> optionlist = _repository._dbContext.PX_QuestionsOptions.Where(x => x.QuestionsId == q.Id).OrderBy(x => x.OptionName).ToList();
                PX_ExamUserQuestionsDto erq = new PX_ExamUserQuestionsDto();
                erq.PX_QuestionOption = optionlist;
                questionlist.Remove(q);
                //处理PX_ExamRecordQuestion 数据  需要从试题表及试题选项表中关联
                erq.Mark01 = q.QuestionManagementType;
                erq.PersonID = Id;
                erq.Id = Guid.NewGuid();
                erq.QuesiontID = q.Id;
                erq.QuestionContent = q.QuestionManagementContent;
                erq.CorrectOption = "";
                optionlist.Where(a => a.IsAnswer == "是").OrderBy(x => x.OptionName).ToList().ForEach(x => erq.CorrectOption += x.OptionName + ",");
                erq.CorrectOption = erq.CorrectOption.TrimEnd(',');
                erq.dxda = new List<String>();
                //erq.dxda.Add("123");
                list.Add(erq);

                return randomQuestion(Id, examnum, questionlist, list);
            }


        }

    }
}
